package com.sias.applicationcontext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 吴文杰
 * @version 1.0
 * @since 2023/5/31 15:59
 */
@SuppressWarnings("all")
public class ApplicationContext02 {
  private static final Logger LOG = LoggerFactory.getLogger(ApplicationContext02.class);

  public static void main(String[] args) {
    // testClassPathXmlApplicationContext();
    // DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    // System.out.println("读取之前....");
    // for (String name : beanFactory.getBeanDefinitionNames()) {
    //   System.out.println(name);
    // }
    // XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
    // reader.loadBeanDefinitions(new ClassPathResource("b01.xml"));
    // System.out.println("读取之后....");
    // for (String name : beanFactory.getBeanDefinitionNames()) {
    //   System.out.println(name);
    // }


    // testAnnotationConfigApplicationContext();
    testAnnotationConfigServletWebServerApplicationContext();
  }

  // 较为经典的容器 基于classpath下xml 格式的配置文件来创建
  private static void testClassPathXmlApplicationContext() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("b01.xml");
    for (String name : context.getBeanDefinitionNames()) {
      System.out.println(name);
    }

    System.out.println(context.getBean(Bean2.class).getBean1());
  }

  // 基于磁盘路径下 xml 格式的配置文件来创建
  private static void testFileSystemXmlApplicationContext() {
  }

  // 较为经典的容器 基于java配置类来创建
  private static void testAnnotationConfigApplicationContext() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

    for (String name : context.getBeanDefinitionNames()) {
      System.out.println(name);
    }

    Bean2 bean = context.getBean(Bean2.class);
    System.out.println(bean.getBean1());
  }

  // 较为经典的容器 基于java配置类来创建 用于web环境
  private static void testAnnotationConfigServletWebServerApplicationContext() {
    AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);
  }

  @Configuration
  static class WebConfig {
    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
      return new TomcatServletWebServerFactory();
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
      return new DispatcherServlet();
    }

    @Bean
    public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
      return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
    }

    @Bean("/hello")
    public Controller controller() {
      return new Controller() {
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
          response.getWriter().print("hello");
          return null;
        }
      };
    }
  }


  @Configuration
  static class Config {
    @Bean
    public Bean1 bean1() {
      return new Bean1();
    }

    @Bean
    public Bean2 bean2(Bean1 bean1) {
      Bean2 bean2 = new Bean2();
      bean2.setBean1(bean1);
      return bean2;
    }
  }


  static class Bean1 {
  }

  static class Bean2 {
    private Bean1 bean1;

    public Bean1 getBean1() {
      return bean1;
    }

    public void setBean1(Bean1 bean1) {
      this.bean1 = bean1;
    }
  }

}
